package com.music.note_android.ui.editor

import android.graphics.*
import android.os.Handler
import android.os.Looper
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.Executors
import kotlin.math.max
import kotlin.math.min

/**
 * 画布性能优化工具类
 * 负责内存管理、对象池、异步处理等优化功能
 */
class CanvasOptimizer {
    
    companion object {
        private const val MAX_PAINT_POOL_SIZE = 20
        private const val MAX_PATH_POOL_SIZE = 50
        private const val MAX_BITMAP_CACHE_SIZE = 10
        private const val CLEANUP_INTERVAL = 30000L // 30秒清理一次
    }
    
    // 对象池
    private val paintPool = mutableListOf<Paint>()
    private val pathPool = mutableListOf<Path>()
    private val rectPool = mutableListOf<RectF>()
    
    // Bitmap缓存
    private val bitmapCache = ConcurrentHashMap<String, Bitmap>()
    private val bitmapUsageCount = ConcurrentHashMap<String, Int>()
    
    // 异步处理线程池
    private val backgroundExecutor = Executors.newFixedThreadPool(2)
    private val mainHandler = Handler(Looper.getMainLooper())
    
    // 清理任务
    private val cleanupRunnable = object : Runnable {
        override fun run() {
            performCleanup()
            mainHandler.postDelayed(this, CLEANUP_INTERVAL)
        }
    }
    
    init {
        // 启动定期清理任务
        mainHandler.postDelayed(cleanupRunnable, CLEANUP_INTERVAL)
    }
    
    /**
     * 获取Paint对象（从对象池）
     */
    fun obtainPaint(): Paint {
        synchronized(paintPool) {
            return if (paintPool.isNotEmpty()) {
                paintPool.removeAt(paintPool.size - 1)
            } else {
                Paint().apply {
                    isAntiAlias = true
                }
            }
        }
    }
    
    /**
     * 回收Paint对象到对象池
     */
    fun recyclePaint(paint: Paint) {
        synchronized(paintPool) {
            if (paintPool.size < MAX_PAINT_POOL_SIZE) {
                paint.reset()
                paintPool.add(paint)
            }
        }
    }
    
    /**
     * 获取Path对象（从对象池）
     */
    fun obtainPath(): Path {
        synchronized(pathPool) {
            return if (pathPool.isNotEmpty()) {
                pathPool.removeAt(pathPool.size - 1)
            } else {
                Path()
            }
        }
    }
    
    /**
     * 回收Path对象到对象池
     */
    fun recyclePath(path: Path) {
        synchronized(pathPool) {
            if (pathPool.size < MAX_PATH_POOL_SIZE) {
                path.reset()
                pathPool.add(path)
            }
        }
    }
    
    /**
     * 获取RectF对象（从对象池）
     */
    fun obtainRect(): RectF {
        synchronized(rectPool) {
            return if (rectPool.isNotEmpty()) {
                rectPool.removeAt(rectPool.size - 1)
            } else {
                RectF()
            }
        }
    }
    
    /**
     * 回收RectF对象到对象池
     */
    fun recycleRect(rect: RectF) {
        synchronized(rectPool) {
            rect.setEmpty()
            rectPool.add(rect)
        }
    }
    
    /**
     * 缓存Bitmap
     */
    fun cacheBitmap(key: String, bitmap: Bitmap) {
        if (bitmapCache.size >= MAX_BITMAP_CACHE_SIZE) {
            // 移除最少使用的Bitmap
            val leastUsedKey = bitmapUsageCount.minByOrNull { it.value }?.key
            leastUsedKey?.let {
                bitmapCache.remove(it)?.recycle()
                bitmapUsageCount.remove(it)
            }
        }
        
        bitmapCache[key] = bitmap
        bitmapUsageCount[key] = 0
    }
    
    /**
     * 获取缓存的Bitmap
     */
    fun getCachedBitmap(key: String): Bitmap? {
        val bitmap = bitmapCache[key]
        if (bitmap != null) {
            bitmapUsageCount[key] = (bitmapUsageCount[key] ?: 0) + 1
        }
        return bitmap
    }
    
    /**
     * 异步执行任务
     */
    fun executeAsync(task: () -> Unit) {
        backgroundExecutor.execute(task)
    }
    
    /**
     * 异步执行任务并在主线程回调结果
     */
    fun <T> executeAsyncWithCallback(
        backgroundTask: () -> T,
        mainThreadCallback: (T) -> Unit
    ) {
        backgroundExecutor.execute {
            val result = backgroundTask()
            mainHandler.post {
                mainThreadCallback(result)
            }
        }
    }
    
    /**
     * 优化Path对象
     * 简化路径点，减少绘制复杂度
     */
    fun optimizePath(originalPath: Path, tolerance: Float = 2.0f): Path {
        val optimizedPath = obtainPath()
        
        // TODO: 实现Douglas-Peucker算法简化路径
        // 这里先简单复制原路径
        optimizedPath.set(originalPath)
        
        return optimizedPath
    }
    
    /**
     * 计算可见区域
     */
    fun calculateVisibleBounds(
        viewWidth: Int,
        viewHeight: Int,
        offsetX: Float,
        offsetY: Float,
        scale: Float
    ): RectF {
        val bounds = obtainRect()
        
        // 计算可见区域在画布坐标系中的范围
        bounds.left = -offsetX / scale
        bounds.top = -offsetY / scale
        bounds.right = bounds.left + viewWidth / scale
        bounds.bottom = bounds.top + viewHeight / scale
        
        // 扩展一些边界以处理边缘情况
        val margin = max(viewWidth, viewHeight) / scale * 0.1f
        bounds.inset(-margin, -margin)
        
        return bounds
    }
    
    /**
     * 检查笔画是否在可见区域内
     */
    fun isStrokeVisible(stroke: Stroke, visibleBounds: RectF): Boolean {
        val strokeBounds = calculateStrokeBounds(stroke)
        return RectF.intersects(strokeBounds, visibleBounds)
    }
    
    /**
     * 计算笔画边界
     */
    private fun calculateStrokeBounds(stroke: Stroke): RectF {
        val bounds = obtainRect()
        
        if (stroke.points.isNotEmpty()) {
            var minX = Float.MAX_VALUE
            var minY = Float.MAX_VALUE
            var maxX = Float.MIN_VALUE
            var maxY = Float.MIN_VALUE
            
            stroke.points.forEach { point ->
                minX = min(minX, point.x)
                minY = min(minY, point.y)
                maxX = max(maxX, point.x)
                maxY = max(maxY, point.y)
            }
            
            // 考虑笔画宽度
            val halfWidth = stroke.width / 2f
            bounds.set(
                minX - halfWidth,
                minY - halfWidth,
                maxX + halfWidth,
                maxY + halfWidth
            )
        }
        
        return bounds
    }
    
    /**
     * 批量处理笔画
     * 将多个小笔画合并为一个路径以减少绘制调用
     */
    fun batchStrokes(strokes: List<Stroke>): List<BatchedStroke> {
        val batches = mutableListOf<BatchedStroke>()
        val currentBatch = mutableListOf<Stroke>()
        var currentTool: DrawingTool? = null
        var currentColor: Int? = null
        var currentWidth: Float? = null
        
        strokes.forEach { stroke ->
            // 检查是否可以批处理
            if (currentTool == stroke.tool && 
                currentColor == stroke.color && 
                currentWidth == stroke.width &&
                currentBatch.size < 10) { // 限制批处理大小
                
                currentBatch.add(stroke)
            } else {
                // 完成当前批次
                if (currentBatch.isNotEmpty()) {
                    batches.add(BatchedStroke(
                        tool = currentTool!!,
                        color = currentColor!!,
                        width = currentWidth!!,
                        strokes = currentBatch.toList()
                    ))
                    currentBatch.clear()
                }
                
                // 开始新批次
                currentTool = stroke.tool
                currentColor = stroke.color
                currentWidth = stroke.width
                currentBatch.add(stroke)
            }
        }
        
        // 处理最后一个批次
        if (currentBatch.isNotEmpty() && currentTool != null) {
            val tool = currentTool!!
            batches.add(BatchedStroke(
                tool = tool,
                color = currentColor!!,
                width = currentWidth!!,
                strokes = currentBatch.toList()
            ))
        }
        
        return batches
    }
    
    /**
     * 执行清理任务
     */
    private fun performCleanup() {
        // 清理未使用的缓存Bitmap
        val unusedKeys = bitmapUsageCount.filter { it.value == 0 }.keys
        unusedKeys.forEach { key ->
            bitmapCache.remove(key)?.recycle()
            bitmapUsageCount.remove(key)
        }
        
        // 重置使用计数
        bitmapUsageCount.replaceAll { _, _ -> 0 }
        
        // 建议垃圾回收
        System.gc()
    }
    
    /**
     * 释放资源
     */
    fun release() {
        mainHandler.removeCallbacks(cleanupRunnable)
        backgroundExecutor.shutdown()
        
        // 清理缓存
        bitmapCache.values.forEach { it.recycle() }
        bitmapCache.clear()
        bitmapUsageCount.clear()
        
        // 清理对象池
        paintPool.clear()
        pathPool.clear()
        rectPool.clear()
    }
    
    /**
     * 批处理笔画数据类
     */
    data class BatchedStroke(
        val tool: DrawingTool,
        val color: Int,
        val width: Float,
        val strokes: List<Stroke>
    )
}